package com.skt.controller;

import com.skt.domain.DTO.request.RentalCalculateRequest;
import com.skt.domain.DTO.request.RentalCheckoutRequest;
import com.skt.domain.VO.RentalCalculateVO;
import com.skt.domain.VO.RentalCheckoutVO;
import com.skt.exception.BusinessException;
import com.skt.exception.RentalErrorCode;
import com.skt.exception.RentalException;
import com.skt.service.RentalService;
import com.skt.utils.LogUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;

@RestController
@RequestMapping("/rental")
@RequiredArgsConstructor
@Tag(name = "租赁流程接口")
public class RentalController {

    private final RentalService rentalService;

    @Operation(
            summary = "计算租赁费用",
            description = "计算选定商品的租赁总费用、押金和明细。基于选中的购物车项、租赁开始和结束日期进行费用计算。"
    )
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "计算成功，返回详细的费用明细"),
            @ApiResponse(responseCode = "400", description = "请求参数错误，如日期不合法或购物车项不存在"),
            @ApiResponse(responseCode = "401", description = "未授权访问"),
            @ApiResponse(responseCode = "404", description = "购物车项或服装不存在")
    })
    @PostMapping("/calculate")
    public ResponseEntity<RentalCalculateVO> calculateRental(@Valid @RequestBody RentalCalculateRequest request) {
        // 设置追踪ID
        LogUtil.setTraceId();

        // 开始性能监控
        LogUtil.startTimer("RENTAL_CALCULATE");

        LogUtil.info("RENTAL", "CALCULATE", "开始计算租赁费用: cartItemIds={}, startDate={}, endDate={}",
                request.getCartItemIds(), request.getStartDate(), request.getEndDate());

        try {
            RentalCalculateVO calculateResult = rentalService.calculateRentalCost(request);
            return ResponseEntity.ok(calculateResult);

        } catch (BusinessException e) {
            LogUtil.error("RENTAL", "CALCULATE",
                    "租赁费用计算失败: error={}", e.getMessage());
            throw e;
        } catch (Exception e) {
            LogUtil.error("RENTAL", "CALCULATE", "租赁费用计算异常", e);
            throw RentalException.of(RentalErrorCode.CALCULATION_FAILED);
        } finally {
            // 结束性能监控
            LogUtil.stopTimer();
            // 清理上下文
            LogUtil.clearContext();
        }
    }


    @Operation(
            summary = "租赁结算下单",
            description = "创建租赁订单并初始化支付流程。基于费用计算结果生成正式订单，预占库存并返回支付信息。"
    )
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "下单成功，返回订单详情和支付信息"),
            @ApiResponse(responseCode = "400", description = "请求参数错误，如计算ID失效或库存不足"),
            @ApiResponse(responseCode = "401", description = "未授权访问"),
            @ApiResponse(responseCode = "409", description = "库存冲突或档期已被占用"),
            @ApiResponse(responseCode = "422", description = "业务规则校验失败，如租赁条件不满足")
    })
    @PostMapping("/checkout")
    public ResponseEntity<RentalCheckoutVO> createRentalOrder(@Valid @RequestBody RentalCheckoutRequest request) {
        // 设置追踪ID
        LogUtil.setTraceId();

        // 开始性能监控
        LogUtil.startTimer("RENTAL_CHECKOUT");

        LogUtil.info("RENTAL", "CHECKOUT", "开始租赁结算下单: calculateId={}",
                request.getCalculateId());

        try {
            RentalCheckoutVO checkoutResult = rentalService.createRentalOrder(request);
            return ResponseEntity.ok(checkoutResult);

        } catch (BusinessException e) {
            LogUtil.error("RENTAL", "CHECKOUT",
                    "租赁下单失败: error={}", e.getMessage());
            throw e;
        } catch (Exception e) {
            LogUtil.error("RENTAL", "CHECKOUT", "租赁下单异常", e);
            throw RentalException.of(RentalErrorCode.ORDER_CREATE_FAILED);
        } finally {
            // 结束性能监控
            LogUtil.stopTimer();
            // 清理上下文
            LogUtil.clearContext();
        }
    }
}